package managers.dateManager.beginFrozen.effortChange;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Resource;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.exceptions.TaskManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateBeginFrozenSPEC;

import factories.ResourceFactory;
import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * Task with BeginDate frozen and no relationships (predecessors/successors)
 * </p>
 * <p>
 * <b>Action</b>
 * </p>
 * <p>
 * Change effort of the task "task"
 * </p>
 * <p>
 * <b> Expected</b>
 * <ul>
 * <li>update EndDate</li>
 * <li>update Successors</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 */
public class BeginFrozen_EffortChange_SingleTask_Basic extends TestCase {

	private Task task = null;
	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private TaskManager dateManager = new TaskManager();

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");

		this.task = (Task) TaskFactory.getInstance();
		this.task.setState(new StateBeginFrozenSPEC(task.getState().getDurationModeState()));

		super.setUp();
	}

	public void testReturnedBeanListNotNull() {
		System.out.println("");
		log.debug(" === testReturnedBeanListNotNull");

		float newEffort = 48f;
		log.debug("new duration = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

	}

	public void testReturnedListSizeIsOk() {
		System.out.println("");
		log.debug(" === testReturnedListSizeIsOk");

		float newEffort = 48f;
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}
		assertEquals("Updated bean list size = 1", 1, updatedBeans.size());

	}

	public void testReturnedBeanIsSameAsOriginal() {
		System.out.println("");
		log.debug(" === testReturnedBeanIsSameAsOriginal");

		float newEffort = 48f;
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals("Task given and received are equals", this.task, updatedBeans.get(0));

	}

	public void testEffortChanged() {
		System.out.println("");
		log.debug(" === testDurationChanged");

		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals("Assert Duration has been udated with new Duration", newEffort, updatedBeans.get(0).getEffort());

	}

	public void testEndDateChanged() {
		System.out.println("");
		log.debug(" === testEndDateChanged");

		Date originalEndDate = task.getEndDate();
		float newEffort = 48f;

		log.debug("original EndDate = " + originalEndDate);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertNotSame("Assert endDate has been udated", df.format(originalEndDate), df.format(updatedBeans.get(0).getEndDate()));

	}

	public void testBeginDateIsSame() {
		System.out.println("");
		log.debug(" === testBeginDateIsSame");

		Date originalBeginDate = task.getBeginDate();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("compute with new effort = " + newEffort + "...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("original BeginDate = " + df.format(originalBeginDate) + " and new BeginDate = " + df.format(updatedBeans.get(0).getBeginDate()));
		assertEquals("Assert BeginDate hans't changed", df.format(originalBeginDate), df.format(updatedBeans.get(0).getBeginDate()));

	}

	public void testRevertGivesOriginalEffort() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalEffort");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved effort = " + updatedBeans.get(0).getEffort() + " & original effort = " + originalEffort);
		assertEquals("Assert effort reverted to original", originalEffort, updatedBeans.get(0).getEffort());

	}

	public void testRevertGivesOriginalBeginDate() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalBeginDate");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEFfort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEFfort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEFfort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals("Assert BeginDate reverted to original", originalBeginDate, updatedBeans.get(0).getBeginDate());

	}

	public void testRevertGivesOriginalEndDate() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalEndDate");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved EndDate = " + updatedBeans.get(0).getEndDate() + " & original BeginDate = " + originalEndDate);
		assertEquals("Assert EndDate reverted to original", originalEndDate, updatedBeans.get(0).getEndDate());

	}

	public void testRevertGivesOriginalEffortInManualChainingMode() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalEffortInManualChainingMode");
		this.task.setState(new StateBeginFrozenSPEC(task.getState().getDurationModeState()));

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original duration = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved effort = " + updatedBeans.get(0).getDuration() + " & original Duration = " + originalEffort);
		assertEquals("Assert effort reverted to original", originalEffort, updatedBeans.get(0).getEffort());

	}

	public void testRevertGivesOriginalBeginDateInManualChainingMode() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalBeginDateInManualChainingMode");
		this.task.setState(new StateBeginFrozenSPEC(task.getState().getDurationModeState()));

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals("Assert BeginDate reverted to original", originalBeginDate, updatedBeans.get(0).getBeginDate());

	}

	public void testRevertGivesOriginalEndDateManualChainingMode() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalEndDateManualChainingMode");
		this.task.setState(new StateBeginFrozenSPEC(task.getState().getDurationModeState()));

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original effort...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, originalEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager .manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved EndDate = " + updatedBeans.get(0).getEndDate() + " & original BeginDate = " + originalEndDate);
		assertEquals("Assert EndDate reverted to original", originalEndDate, updatedBeans.get(0).getEndDate());

	}

	public void testDurations() {
		System.out.println("");
		log.debug(" === testDurations");

		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(48f, updatedBeans.get(0).getDuration());

	}

	public void testDurationsWithOneResourceFullTime() {
		System.out.println("");
		log.debug(" === testDurationsWithOneResourceFullTime");
		
		this.task.setResource(ResourceFactory.getInstance());

		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(48f, updatedBeans.get(0).getDuration());

	}
	
	public void testDurationsWithOneResourceHalfTime() {
		System.out.println("");
		log.debug(" === testDurationsWithOneResourceHalfTime");
		
		Resource resource = ResourceFactory.getInstance();
		resource.setRatio(50);
		this.task.setResource(resource);

		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(96f, updatedBeans.get(0).getDuration());

	}
	
	public void testDurationsWithTwoResources() {
		System.out.println("");
		log.debug(" === testDurationsWithTwoResources");
		
		this.task.setResource(ResourceFactory.getInstance());
		this.task.addResource(ResourceFactory.getInstance());

		float originalEffort = task.getEffort();
		float newEffort = 48f;

		log.debug("original effort = " + originalEffort);
		log.debug("new effort = " + newEffort);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_effort, newEffort);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(24f, updatedBeans.get(0).getDuration());

	}}